package com.moose.operator.web.service.impl.sms;

import com.moose.operator.constant.CacheNameConstant;
import com.moose.operator.constant.SecurityConstant;
import com.moose.operator.constant.SmsTypeConstant;
import com.moose.operator.mapper.SmsCodeMapper;
import com.moose.operator.model.domain.SmsCodeDO;
import com.moose.operator.model.dto.SmsCodeDTO;
import com.moose.operator.model.param.SmsCodeParam;
import com.moose.operator.util.RedisUtil;
import com.moose.operator.web.service.AccountService;
import com.moose.operator.web.service.SmsCodeSenderService;
import com.moose.operator.web.service.UserInfoService;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

/**
 * <p>
 * Description:
 * </p>
 *
 * @author taohua
 * @version v1.0.0
 * @date 2020-06-15 23:23:23:23
 * @see com.moose.operator.web.service.impl
 */
@Slf4j
@Component
public class DefaultSmsCodeSenderServiceImpl implements SmsCodeSenderService {

  @Resource
  private SmsCodeMapper smsCodeMapper;

  @Resource
  private AccountService accountService;

  @Resource
  private UserInfoService userInfoService;

  @Resource private RedisUtil redisUtil;

  @Transactional(rollbackFor = Exception.class)
  @Override public Boolean sendSmsCode(SmsCodeParam smsCodeParam) {

    // 发送短信
    sendAndSaveSmsCode(smsCodeParam);

    return Boolean.TRUE;
  }

  @Override public void setSmsCodeCacheExpire(String phone) {
    String smsCodeKey =
        String.format(CacheNameConstant.SMS_CODE_KEY, SmsTypeConstant.RESET_PHONE, phone);
    redisUtil.removeValue(smsCodeKey);
  }

  @Override public SmsCodeDTO getSmsCodeFromCacheByPhone(String phone) {
    String smsCodeKey =
        String.format(CacheNameConstant.SMS_CODE_KEY, SmsTypeConstant.RESET_PHONE, phone);
    return (SmsCodeDTO) redisUtil.getValue(smsCodeKey);
  }

  private void sendAndSaveSmsCode(SmsCodeParam smsCodeParam) {
    // 生成短信验证码
    String smsCode = RandomStringUtils.randomNumeric(6);

    String phoneNumber = smsCodeParam.getPhone();

    String smsType = smsCodeParam.getType();

    // reset save sms code to redis
    String smsCodeKey = String.format(CacheNameConstant.SMS_CODE_KEY, smsType, phoneNumber);

    // TODO: get sms code not expired return ?
    SmsCodeDTO smsCodeDTO = (SmsCodeDTO) redisUtil.getValue(smsCodeKey);
    if (ObjectUtils.isNotEmpty(smsCodeDTO) && !smsCodeDTO.getExpired()) {
      return;
    }

    // sms code save db
    SmsCodeDO smsCodeDO = new SmsCodeDO();
    smsCodeDO.setPhone(phoneNumber);
    smsCodeDO.setType(smsType);
    smsCodeDO.setCode(smsCode);
    smsCodeMapper.insertSmsCode(smsCodeDO);

    smsCodeDTO =
        new SmsCodeDTO(smsCode, smsType, SecurityConstant.SMS_TIME_OF_TIMEOUT);
    redisUtil.cacheValue(
        smsCodeKey,
        smsCodeDTO,
        SecurityConstant.SMS_TIME_OF_TIMEOUT,
        TimeUnit.SECONDS
    );
    log.info("phone number [{}] send sms code [{}]", phoneNumber, smsCode);
  }
}
